﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

#pragma once
#include "GcmpModelInterface.h"
#include "IObject.h"
#include <string>
#include <vector>
#include <future>
#include "ElementId.h"
#include "IDataset.h"
#include "GcmpApiDeclaration.h"

namespace gcmp
{
    class IDocument;
    class IElement;
    class UniIdentity;

    struct GCMP_MODEL_INTERFACE_EXPORT TemplateInput
    {
        bool isTemplate;
        std::wstring elementSetId;
        std::wstring relatedElementSetId;
    };

    /// \brief 构件集接口
    ///
    /// 提供构件集的操作接口
    class GCMP_MODEL_INTERFACE_EXPORT IElementSet : public IObject
    {
        DEFINE_CAST_DERIVED(gcmp::IElementSet, gcmp::IObject);

    public:

        static IElementSet* Get();

        /// \brief 按类别查询对象的版本
        /// \param projectId 工程Id
        /// \param majorType 专业
        /// \param elementSetId 工作单元id
        /// \param category 类别
        /// \param idToVersion 输出
        /// \return 返回是否查询成功
        virtual bool QueryElementVersionsByCategory(
            const std::wstring& projectId,
            const std::wstring& majorType,
            const std::wstring& elementSetId,
            const std::wstring& category,
            int version,
            std::map<Int64, Int32>& idToVersion
        ) = 0;

        /// \brief 基于给定的Id和版本申请对象编辑权限
        /// \param pDoc 主文档
        /// \param projectId 工程Id
        /// \param majorType 专业
        /// \param elementSetId 工作单元id
        /// \param idToVersion 对象Id和版本的映射。
        ///     如果此版本不是最新版本，说明有人更新过了，失败；
        ///     如果坚持继续申请，需要重复下载最新版本、申请流程。
        /// \return 返回是否申请成功
        virtual bool AcquireEditPrivileges(
            IDocument* pDoc,
            const std::wstring& projectId,
            const std::wstring& majorType,
            const std::wstring& elementSetId,
            const std::map<Int64, Int32>& idToVersion
        ) = 0;

        /// \brief 按需加载构件
        /// \param pDoc 主文档
        /// \param projectId 工程Id
        /// \param majorType 专业
        /// \param ids 欲加载构件的id列表
        /// \param exclDeps 是否加载强弱依赖数据
        /// \param elements 输出
        /// \return 返回是否添加成功
        virtual bool LoadOnDemand(IDocument* pDoc, const std::wstring& projectId, const std::wstring& majorType, const std::vector<ElementId>& ids, bool exclDeps, std::vector<std::pair<OwnerPtr<IElement>,Int32>>& elements) = 0;

        /// \brief 按需参照整个工作单元
        /// \param pDoc 主文档
        /// \param projectId 工程Id
        /// \param majorType 专业
        /// \param elementSetId 工作单元id
        /// \param ver 工作单元版本
        /// \param elements 输出
        /// \return 返回是否添加成功
        virtual bool LoadOnDemand(IDocument* pDoc, const std::wstring& projectId, const std::wstring& majorType, const std::string& elementSetId, int ver, std::vector<std::pair<OwnerPtr<IElement>, Int32>>& elements) = 0;

        /// \brief 根据category按需加载构件
        /// \param pDoc 主文档
        /// \param projectId 工程Id
        /// \param majorType 专业
        /// \param elementSetId 构件集id
        /// \param ver 工作单元版本
        /// \param elements 输出
        /// \return 返回是否添加成功
        GCMP_DEPRECATED_API(2021/12/10) virtual bool LoadOnDemand(IDocument* pDoc, const std::wstring& projectId, const std::wstring& majorType, const std::wstring& elementSetId, const std::map <std::wstring, int>& categories, std::vector<std::pair<OwnerPtr<IElement>, Int32>>& elements) = 0;

        /// \brief 根据category按需加载构件
        /// \param pDoc 主文档
        /// \param projectId 工程Id
        /// \param majorType 专业
        /// \param elementSetId 构件集id
        /// \param idToVersion 对象和Id的版本
        /// \param elements 输出
        /// \return 返回是否添加成功
        virtual bool LoadOnDemand(
            IDocument* pDoc, 
            const std::wstring& projectId,
            const std::wstring& majorType,
            const std::wstring& elementSetId,
            const std::map<Int64, Int32>& idToVersion,
            std::vector<std::pair<OwnerPtr<IElement>, Int32>>& elements
        ) = 0;

        /// \brief 异步上传修改，生成新版本。
        ///
        /// 发布的是BIM标准数据，供协作用。
        /// \param publisher 提供对象的标准数据内容，传入nullptr则不发布对象的任何内容。
        ///     目前实现时传入nullptr，则发布预定义的标准数据，可能不是想要的、或者是不够的。
        /// \param opt “mvd” 选项
        /// \param targetVersion: 用于云端translator(处理MvdOption::Std, MvdOption::Ref, MvdOption::View), -1表示最新
        /// \return std::future<bool> 是否上传成功
        GCMP_OBSOLETE_API(2021 / 11 / 30, Save(IDocument* pDoc, IElementCloudStandardContentPublisher* publisher, MvdOption opt,
            int targetVersion, const std::vector<std::wstring>& categoryFilterIds, std::string& strErrorCodeJson))
        virtual std::future<bool> Save(IDocument* pDoc, IElementCloudStandardContentPublisher* publisher, MvdOption opt, int targetVersion, const std::vector<std::wstring>& categoryFilterIds) = 0;
        virtual std::future<bool> Save(IDocument* pDoc, IElementCloudStandardContentPublisher* publisher, MvdOption opt, 
            int targetVersion, const std::vector<std::wstring>& categoryFilterIds, std::string& strErrorCodeJson) = 0;

        /// \brief 提交工作单元
        /// \param pDoc 主文档
        /// \param datasetId 待提交的工作单元id
        /// \param publisher 提供对象的标准数据内容，传入nullptr则不发布对象的任何内容。
        /// \param opt “mvd” 选项
        /// \param targetVersion: 用于云端translator(处理MvdOption::Std, MvdOption::Ref, MvdOption::View), -1表示最新
        /// \param categoryFilterIds 用于category过滤
        /// \param isTemplate 表明是否当前数据来自模板
        /// \param comment 提交工作单元时的注释
        virtual std::future<OwnerPtr<IDatasetVersion>> Publish(IDocument* pDoc, IElementCloudStandardContentPublisher* publisher, MvdOption mvd, int targetVersion, const std::wstring& comment, const std::vector<std::wstring>& categoryFilterIds, const TemplateInput& input, std::string& strErrorCodeJson) = 0;

        /// \brief 获取需要更新构件
        /// \param pDoc 主文档
        /// \param projectId 工程Id
        /// \param majorType 专业
        /// \param elementSetId 构件级id
        /// \param ids 输出
        virtual bool GetOutdatedElementIds(const IDocument* pDoc, const std::wstring& projectId, const std::wstring& majorType, const std::string& elementSetId, std::vector<ElementId>& ids) = 0;

        /// \brief 获取需要更新构件
        /// \param pDoc 主文档
        /// \param projectId 工程Id
        /// \param majorType 专业
        /// \param inputIds 输入构件id列表
        /// \param outdatedIds 输出版本过期的id列表
        virtual bool GetOutdatedElementIds(const IDocument* pDoc, const std::wstring& projectId, const std::wstring& majorType, const std::vector<ElementId>& inputIds, std::vector<ElementId>& outdatedIds) = 0;

        /// \brief 析构函数
        virtual ~IElementSet();

    protected:
        static IElementSet * s_instance;
    };
}
